import requests
import json
import base64
import hashlib
import hmac
import time
from urllib.parse import urlencode, quote

class CloudBase:
    """微信云托管基础类，用于与微信云托管服务交互"""
    
    def __init__(self, config):
        """
        初始化云托管客户端
        
        Args:
            config (dict): 配置信息，包含env, appid, secret
        """
        self.env = config.get('env', '')
        self.appid = config.get('appid', '')
        self.secret = config.get('secret', '')
        self.access_token = None
        self.token_expire_time = 0
        
    def _get_access_token(self):
        """获取微信云托管访问令牌"""
        if self.access_token and time.time() < self.token_expire_time:
            return self.access_token
            
        url = f"https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={self.appid}&secret={self.secret}"
        response = requests.get(url)
        result = response.json()
        
        if 'access_token' in result:
            self.access_token = result['access_token']
            self.token_expire_time = time.time() + result.get('expires_in', 7200) - 300  # 提前5分钟过期
            return self.access_token
        else:
            raise Exception(f"获取access_token失败: {result}")
    
    def getStorage(self):
        """获取对象存储客户端"""
        return CloudStorage(self)
        
class CloudStorage:
    """微信云托管对象存储类，用于处理文件上传下载"""
    
    def __init__(self, cloud_base):
        """
        初始化对象存储客户端
        
        Args:
            cloud_base (CloudBase): 云托管客户端实例
        """
        self.cloud_base = cloud_base
        
    def get_file(self, file_id):
        """
        从对象存储中获取文件
        
        Args:
            file_id (str): 文件ID
            
        Returns:
            bytes: 文件内容的二进制数据
        """
        try:
            # 获取文件下载链接
            download_url = self._get_temp_file_url(file_id)
            
            # 下载文件内容
            response = requests.get(download_url)
            if response.status_code == 200:
                return response.content
            else:
                raise Exception(f"下载文件失败，状态码: {response.status_code}, 响应: {response.text}")
        except Exception as e:
            raise Exception(f"获取文件失败: {str(e)}")
    
    def put_file(self, file_name, file_content):
        """
        上传文件到对象存储
        
        Args:
            file_name (str): 文件名
            file_content (bytes): 文件内容的二进制数据
            
        Returns:
            str: 上传成功后的文件ID
        """
        try:
            # 获取上传链接
            upload_info = self._get_upload_url(file_name)
            
            # 上传文件
            upload_url = upload_info.get('url', '')
            token = upload_info.get('token', '')
            authorization = upload_info.get('authorization', '')
            file_id = upload_info.get('file_id', '')
            cos_file_id = upload_info.get('cos_file_id', '')
            
            headers = {
                'Authorization': authorization,
                'x-cos-security-token': token
            }
            
            response = requests.put(upload_url, data=file_content, headers=headers)
            
            if response.status_code == 200:
                return file_id
            else:
                raise Exception(f"上传文件失败，状态码: {response.status_code}, 响应: {response.text}")
        except Exception as e:
            raise Exception(f"上传文件失败: {str(e)}")
    
    def _get_temp_file_url(self, file_id):
        """获取临时文件下载链接"""
        access_token = self.cloud_base._get_access_token()
        url = f"https://api.weixin.qq.com/tcb/batchdownloadfile?access_token={access_token}"
        
        data = {
            "env": self.cloud_base.env,
            "file_list": [{"fileid": file_id, "max_age": 7200}]
        }
        
        response = requests.post(url, json=data)
        result = response.json()
        
        if result.get('errcode') == 0 and 'file_list' in result and len(result['file_list']) > 0:
            return result['file_list'][0].get('download_url', '')
        else:
            raise Exception(f"获取文件下载链接失败: {result}")
    
    def _get_upload_url(self, file_path):
        """获取文件上传链接"""
        access_token = self.cloud_base._get_access_token()
        url = f"https://api.weixin.qq.com/tcb/uploadfile?access_token={access_token}"
        
        data = {
            "env": self.cloud_base.env,
            "path": file_path
        }
        
        response = requests.post(url, json=data)
        result = response.json()
        
        if result.get('errcode') == 0:
            return {
                'url': result.get('url', ''),
                'token': result.get('token', ''),
                'authorization': result.get('authorization', ''),
                'file_id': result.get('file_id', ''),
                'cos_file_id': result.get('cos_file_id', '')
            }
        else:
            raise Exception(f"获取文件上传链接失败: {result}")
